package com.wz.jaav.rtda;

import com.wz.jaav.util.ByteArrayConveter;

import java.util.Arrays;

public class OperandStack {
    private int topIndex;
    private Slot[] slots;
    public OperandStack(int maxLocals){
        if (maxLocals > 0){
            slots = new Slot[maxLocals];
        }
    }

    public void pushFloat(float val){
        Slot slot = new Slot();
        slot.setNum(ByteArrayConveter.getByteArray(val));

        this.slots[this.topIndex]= slot;
        this.topIndex++;
    }

    public float popFloat(){
        this.topIndex--;
        float num = ByteArrayConveter.getFloat(slots[this.topIndex].getNum(), 0);
        slots[this.topIndex] = null;
        return num;
    }

    public void pushInt(int val){
        Slot slot = new Slot();
        slot.setNum(ByteArrayConveter.getByteArray(val));

        this.slots[this.topIndex]= slot;
        this.topIndex++;
    }

    public int popInt(){
        this.topIndex--;
        int num = ByteArrayConveter.getInt(slots[this.topIndex].getNum(), 0);
        slots[this.topIndex] = null;
        return num;
    }

    public void pushLong(long num){
        byte[] numArray = ByteArrayConveter.getByteArray(num);
        push64bitNum(numArray);
    }

    public long popLong(){
        Slot higher = this.slots[this.topIndex];
        byte[] higherByte = higher.getNum();

        this.topIndex = this.topIndex - 1;
        Slot lower = this.slots[this.topIndex];
        byte[] lowerByte = lower.getNum();
        long num = ByteArrayConveter.synthesisIntoLong(higherByte, lowerByte);
        slots[this.topIndex] = null;
        slots[this.topIndex + 1] = null;
        return num;
    }

    public void pushDouble(double num){
        byte[] numArray = ByteArrayConveter.getByteArray(num);
        push64bitNum(numArray);
    }

    public double popDouble(){
        Slot higher = this.slots[this.topIndex];
        byte[] higherByte = higher.getNum();

        this.topIndex = this.topIndex - 1;
        Slot lower = this.slots[this.topIndex];
        byte[] lowerByte = lower.getNum();
        double num = ByteArrayConveter.synthesisIntoDouble(higherByte, lowerByte);
        slots[this.topIndex] = null;
        slots[this.topIndex + 1] = null;
        return num;
    }

    private void push64bitNum(byte[] numArray){
        Slot lower = new Slot();
        lower.setNum(ByteArrayConveter.getLowerByte32(numArray));

        Slot higher = new Slot();
        higher.setNum(ByteArrayConveter.getHigherByte32(numArray));

        this.slots[this.topIndex] = lower;
        this.slots[this.topIndex + 1] = higher;
        this.topIndex = this.topIndex + 1;
    }

    @Override
    public String toString() {
        return "OperandStack{" +
                "topIndex=" + topIndex +
                ", slots=" + Arrays.toString(slots) +
                '}';
    }

    public static void main(String[] args) {
        OperandStack operandStack = new OperandStack(10);
        operandStack.pushLong(-1000L);
        System.out.println(operandStack.toString());
        System.out.println(operandStack.popLong());
        System.out.println(operandStack.toString());

        operandStack.pushDouble(-98.34D);
        System.out.println(operandStack.popDouble());

        operandStack.pushFloat(-0.1f);
        System.out.println(operandStack.popFloat());
    }
}